package com.example.downloader.model;

import android.os.AsyncTask;

import java.io.File;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import static com.example.downloader.model.DownloadCallback.FLAG_CANCLED;
import static com.example.downloader.model.DownloadCallback.FLAG_ERROR;
import static com.example.downloader.model.DownloadCallback.FLAG_FINISHED;
import static com.example.downloader.model.DownloadCallback.FLAG_FREE;

/**
 * Created by Administrator on 2017/9/6 0006.
 */

public class BaseDownloader<Result> {
    final Map<String, DownloadTask<Result>> mDownloadingWorks = new HashMap<>();
    private final Map<Integer, DownloadCallback<Result>> mUiWorks = new HashMap<>();
    final Set<String> mSuccessedWorks;
    final String mDownloadPath;

    public BaseDownloader(String downloadPath) {
        File file = new File(downloadPath);
        if (!file.exists()) {
            file.mkdirs();
        }
        mDownloadPath = downloadPath;
        mSuccessedWorks = new HashSet<>();
//        File file = new File(downloadPath);
//        if (file.exists()) {
//            File[] files = file.listFiles(new FileFilter() {
//                @Override
//                public boolean accept(File pathname) {
//                    if (pathname.isDirectory())
//                        return true;
//                    return false;
//                }
//            });
//            if (file.length() > 0) {
//                for (File f : files) {
//                    try {
//                        int id = Integer.valueOf(f.getName());
//                        mSuccessedWorks.add(id);
//                    } catch (NumberFormatException e) {
//
//                    }
//                }
//            }
//        }

    }


    public void loadingDownloadState(ProgressAware newAware, DownloadInfo downloadInfo) {
        DownloadCallback<Result> working = mUiWorks.remove(newAware.getId());
        if (working != null) {
            working.interruptUI();
        }

        if (mSuccessedWorks.contains(downloadInfo.uri)) {
            newAware.setDownloadingFinishedState(downloadInfo, getDownloadPath(downloadInfo));
            return;
        }

        DownloadTask<Result> task = mDownloadingWorks.get(downloadInfo.uri);
        DownloadCallback<Result> cachedWorking = task == null ? null : task.getProgressCallback();
        if (cachedWorking == null) {
            newAware.setFreeState(true);
        } else {
            cachedWorking.setProgressAware(newAware);
            mUiWorks.put(newAware.getId(), cachedWorking);
        }
    }


    public boolean downloadFile(ProgressAware aware, DownloadInfo info) {
        if (info == null)
            return false;
        if (mSuccessedWorks.remove(info.uri)) {
            startDownload(aware, info);//重新下载
            return true;
        } else {
            DownloadTask<Result> task = mDownloadingWorks.get(info.uri);
            DownloadCallback<Result> working = task == null ? null : task.getProgressCallback();

            if (working == null) {//如果已经下载成功或者还没有下载
                startDownload(aware, info);
            } else {
                final int curState = working.getState();
                if (curState == FLAG_ERROR || curState == FLAG_FREE || curState == FLAG_CANCLED) {
                    working.release();
                    mDownloadingWorks.remove(info.uri);
                    startDownload(aware, info);
                }
            }
            return true;
        }


    }

    public String getDownloadPath(String name) {
        return mDownloadPath + "/" + name;
    }


    public String getDownloadPath(DownloadInfo info) {
        if (info == null) {
            return getDownloadPath((String) null);
        }
        return getDownloadPath(info.name);
    }


    private DownloadCallback<Result> startDownload(ProgressAware aware, DownloadInfo info) {
        DownloadCallback<Result> working = new DownloadCallback<>(aware, mDownloadingWorks, mSuccessedWorks, info, getDownloadPath(info));
        DownloadTask<Result> task = makeDownloadTask(getDownloadPath(info), info.uri, working);
        mDownloadingWorks.put(info.uri, task);
        mUiWorks.put(aware.getId(), working);
        task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, info.uri, getDownloadPath(info));
//        x.task().start(task);
        return working;
    }

    protected DownloadTask<Result> makeDownloadTask(String filePath, String uri, DownloadCallback<Result> callback) {
//        RequestParams params = new RequestParams(uri);
//        params.setSaveFilePath(filePath);
//        params.setAutoRename(false);
//        params.setMethod(HttpMethod.POST);
//        DownloadTask<Result> fileDownloadTask = new DownloadTask<>(callback);

        return null;
    }


    public int getWorkingState(String uri) {
//        if (id < 0)
//            throw new IllegalArgumentException("download id is <0!!!");
        if (mSuccessedWorks.contains(uri)) {
            return FLAG_FINISHED;
        }

        DownloadCallback<Result> working = getWorkingCallback(uri);
        if (working == null) {
            return FLAG_FREE;
        } else {
            return working.getState();
        }
    }


    DownloadCallback<Result> getWorkingCallback(String uri) {
        DownloadTask<Result> task = mDownloadingWorks.get(uri);
        return task == null ? null : task.getProgressCallback();
    }

    public boolean cancle(String uri) {
        DownloadTask<Result> task = mDownloadingWorks.get(uri);
        if (task == null || task.isCancelled()) {
            return false;
        }
        task.cancel(true);
        return true;
    }

    public void cancleAllWork(boolean release) {
        if (release) {
            mSuccessedWorks.clear();
            Set<Map.Entry<String, DownloadTask<Result>>> entries = mDownloadingWorks.entrySet();
            Iterator<Map.Entry<String, DownloadTask<Result>>> entryIterator = entries.iterator();
            while (entryIterator.hasNext()) {
                Map.Entry<String, DownloadTask<Result>> entry = entryIterator.next();
                DownloadTask<Result> task = entry.getValue();
                DownloadCallback<Result> callback = task.getProgressCallback();
                if (callback != null) {
                    callback.release();
                }
                entryIterator.remove();
            }
            mUiWorks.clear();
        } else {
            Set<Map.Entry<String, DownloadTask<Result>>> entries = mDownloadingWorks.entrySet();
            Iterator<Map.Entry<String, DownloadTask<Result>>> entryIterator = entries.iterator();
            while (entryIterator.hasNext()) {
                Map.Entry<String, DownloadTask<Result>> entry = entryIterator.next();
                entry.getValue().cancel(true);
            }
        }
    }

//    public void release() {
//        mSuccessedWorks.clear();
//
//        Set<Map.Entry<String, DownloadTask<Result>>> entries = mDownloadingWorks.entrySet();
//        Iterator<Map.Entry<String, DownloadTask<Result>>> entryIterator = entries.iterator();
//        while (entryIterator.hasNext()) {
//            Map.Entry<String, DownloadTask<Result>> entry = entryIterator.next();
//            DownloadTask<Result> task = entry.getValue();
//            DownloadCallback<Result> callback = task.getProgressCallback();
//            if (callback != null) {
//                callback.release();
//            }
//            entryIterator.remove();
//        }
//        mUiWorks.clear();
//    }


}
